﻿package peace.htmllooker.node.table
{
/**
 * Класс для расчёта размеров ячеек элементов в коллекции элементов по заданному размеру коллекции. 
 * У ячейки есть 
 * - минимальный, 
 * - пользовательский/пиксельный (пользователь хотел бы такой, если это возможно)
 * - процентный
 * - рекомендованный (обычно, тупо полный размер контента ячейки)
 * размеры. Размеры перечислены в порядке убывания приоритета.
 */
internal class DimensionsArray
{
	/**
	 * полный ожидаемый размер таблицы
	 */	
	public var size:Number;
	/**
	 * чтобы правильно посчитать размеры в процентах
	 */	
	public var cellspacing:Number;
	/**
	 * 
	 */
	protected var dimensions:Array = [];
	
	
	
	/**
	 * сумма минимумов
	 */	
	protected var minTotal:Number = 0;
	/**
	 * сумма рекомендованных
	 */	
	protected var preferredTotal:Number = 0;
	/**
	 * размер для случая size == 0 
	 */	
	protected var pixelPreferredTotal:Number = 0;
	/**
	 * сумма разниц pixel-min для ячеек с pixel-size
	 */
	protected var onlyPixelDifferenceTotal:Number = 0;
	/**
	 * сумма разниц percent-min для ячеек с percent-size
	 */	
	protected var onlyPercentDifferenceTotal:Number = 0;
	/**
	 * сумма разниц preferred-min для ячеек без pixel|percent-size
	 */
	protected var onlyPreferredDifferenceTotal:Number = 0;
	/**
	 * сумма pixel-min для ячеек с pixel-size
	 */	
	protected var onlyPixelTotal:Number = 0;
	/**
	 * сумма percent-min для ячеек с percent-size
	 */	
	protected var onlyPercentTotal:Number = 0;
	/**
	 * сумма preferred-min для ячеек без pixel|percent-size
	 */	
	protected var onlyPreferredTotal:Number = 0;
	
	/**
	 * 
	 */	
	protected var hasPixelCells:Boolean = false;
	/**
	 * 
	 */
	protected var hasPercentCells:Boolean = false;
	/**
	 * есть ли ячейки без явного указания размера 
	 */
	protected var hasEmptySizeCells:Boolean = false;
	
	/**
	 * 
	 * @param size
	 * @param cellspacing
	 * 
	 */	
	public function DimensionsArray (size:Number, cellspacing:Number)
	{
		this.size = size || 0;
		this.cellspacing = cellspacing || 0;
	}
	
	/**
	 * 
	 * @param d TableDimensions
	 * 
	 */
	public function push (d:TableDimensions):void
	{
		if (d.preferred < d.min) d.preferred = d.min;
		
		if (d.pixel)
		{
			if (d.pixel < d.min)	d.pixel = d.min;
			if (d.preferred < d.pixel) d.preferred = d.pixel;
		}
		// не может быть вместе с user
		else if (d.percent)
		{
			d.percent = Math.max (d.min, size * d.percent/100 + cellspacing);
			if (d.preferred < d.percent) d.preferred = d.percent;
		}

		dimensions.push (d);

		minTotal += d.min;
		preferredTotal += d.preferred;
		
		if (d.pixel)
		{
			onlyPixelDifferenceTotal += d.pixel - d.min;
			onlyPixelTotal += d.pixel;
			pixelPreferredTotal += d.pixel; 
			
			hasPixelCells = true;
		}
		else if (d.percent)
		{
			onlyPercentDifferenceTotal += d.percent - d.min;
			onlyPercentTotal += d.percent;
			
			hasPercentCells = true;
		}
		else
		{
			onlyPreferredDifferenceTotal += d.preferred - d.min;
			onlyPreferredTotal += d.preferred;
			pixelPreferredTotal += d.preferred;
			
			hasEmptySizeCells = true;
		}
		
	}
	/**
	 * По массиву величин размеров считаем оптимальное сочетание
	 * 
	 * @param size Number полный ожидаемый размер таблицы
	 * @return массив размеров ячеек
	 * 
	 */
	public function calculateDimensions ():Array
	{
		// считаем, что 0 это без ограничений
		if (size == 0)
		{
			size = pixelPreferredTotal;
		}
		
		var ret:Array = [];
		var delta:Number;
		var d:TableDimensions;
		
		// если меньше суммы минимальных, возвр минимальные
		if (size <= minTotal)
		{
			for (var i : uint = 0; i < dimensions.length; i++) 
			{
				d = TableDimensions(dimensions[i]);
				ret.push (d.min);
			}
		}
		// если не дотягиваем до честных пикселей, режем пиксели
		// onlyPixelDifferenceTotal тут всегда > 0
		else if (size <= minTotal + onlyPixelDifferenceTotal)
		{
			delta = (size - minTotal) / onlyPixelDifferenceTotal;
			for (i = 0; i < dimensions.length; i++) 
			{
				d = TableDimensions(dimensions[i]);
				ret.push (d.pixel ? d.min + (d.pixel - d.min) * delta : d.min);
			}
		}
		// если не дотягиваем до честных процентов, режем проценты
		// onlyPercentDifferenceTotal тут всегда > 0
		else if (size <= minTotal + onlyPixelDifferenceTotal + onlyPercentDifferenceTotal)
		{
			delta = (size - minTotal - onlyPixelDifferenceTotal) / onlyPercentDifferenceTotal;
			for (i = 0; i < dimensions.length; i++) 
			{
				d = TableDimensions(dimensions[i]);
				ret.push (d.percent ? d.min + (d.percent - d.min) * delta : (d.pixel || d.min));
			}
		}
		// если укладываемся по пикселям и процентам
		else
		{
			// если есть ячейки без размера, то тянем пропорционально эти ячейки
			if (hasEmptySizeCells)
			{
				if (onlyPreferredDifferenceTotal == 0)
				{
					delta = (size - onlyPixelTotal - onlyPercentTotal) / onlyPreferredTotal;
					for (i = 0; i < dimensions.length; i++) 
					{
						d = TableDimensions(dimensions[i]);
						ret.push (d.pixel || d.percent || d.preferred * delta);
					}
				}
				else
				{
					delta = (size - minTotal - onlyPixelDifferenceTotal - onlyPercentDifferenceTotal) / onlyPreferredDifferenceTotal;
					for (i = 0; i < dimensions.length; i++) 
					{
						d = TableDimensions(dimensions[i]);
						ret.push (d.pixel || d.percent || d.min + (d.preferred - d.min) * delta);
					}
				}
			}
			// если только размерные ячейки, то тянем за проценты
			else if (hasPercentCells)
			{
				if (onlyPercentDifferenceTotal == 0)
				{
					delta = (size - onlyPixelTotal) / onlyPercentTotal;
					for (i = 0; i < dimensions.length; i++) 
					{
						d = TableDimensions(dimensions[i]);
						ret.push (d.pixel || d.percent * delta);
					}
				}
				else
				{
					delta = (size - minTotal - onlyPixelDifferenceTotal) / onlyPercentDifferenceTotal;
					for (i = 0; i < dimensions.length; i++) 
					{
						d = TableDimensions(dimensions[i]);
						ret.push (d.pixel || d.min + (d.percent - d.min) * delta);
					}
				}
			}
			// есть только пиксельные ячейки, тянем их пропорционально
			else
			{
				if (onlyPixelDifferenceTotal == 0)
				{
					delta = size / onlyPixelTotal;
					for (i = 0; i < dimensions.length; i++) 
					{
						d = TableDimensions(dimensions[i]);
						ret.push (d.pixel * delta);
					}
				}
				else
				{
					delta = (size - minTotal) / onlyPixelDifferenceTotal;
					for (i = 0; i < dimensions.length; i++) 
					{
						d = TableDimensions(dimensions[i]);
						ret.push (d.min + (d.pixel - d.min) * delta);
					}
				}
			}
		}
		
//		trace (ret)

		return ret;
	}
	/**
	 * сумма минимальных значений 
	 * 
	 * @return 
	 * 
	 */	
	public function get min ():Number
	{
		return minTotal;
	}
	/**
	 * сумма предпочтительных значений
	 *  
	 * @return 
	 * 
	 */	
	public function get preferred ():Number
	{
		return preferredTotal;
	}
	
}

}
